package com.gly091020.mixin;

import com.gly091020.MathDragon;
import com.gly091020.MathDragonFun;
import com.gly091020.NetWorkingPackId;
import com.gly091020.client.screen.MathScreen;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.minecraft.entity.Entity;
import net.minecraft.entity.boss.dragon.EnderDragonEntity;
import net.minecraft.entity.boss.dragon.EnderDragonPart;
import net.minecraft.entity.boss.dragon.phase.PhaseManager;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.damage.DamageTypes;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.math.random.Random;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import java.util.List;

import static net.minecraft.entity.boss.dragon.phase.PhaseType.CHARGING_PLAYER;
import static net.minecraft.entity.boss.dragon.phase.PhaseType.SITTING_ATTACKING;

@Mixin(EnderDragonEntity.class)
public abstract class EnderDragonMixin {
    @Shadow @Final private PhaseManager phaseManager;

    @Inject(method = "tickMovement", at = @At("RETURN"))
    public void noChargingPlayer(CallbackInfo ci){
        if(MathDragon.CONFIG.doDragonCharging){return;}
        if (phaseManager.getCurrent().getType() == CHARGING_PLAYER){
            phaseManager.setPhase(SITTING_ATTACKING);
        }
    }

    @Redirect(method = "launchLivingEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;addVelocity(DDD)V"))
    public void noLaunchPlayer(Entity instance, double deltaX, double deltaY, double deltaZ){
        if(MathDragon.CONFIG.doDragonCharging){
            instance.setVelocity(deltaX, deltaY, deltaZ);
            return;
        }
        if(instance instanceof PlayerEntity){
            return;
        }
        instance.setVelocity(deltaX, deltaY, deltaZ);
    }

    @Redirect(method = "damage", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/boss/dragon/EnderDragonEntity;damagePart(Lnet/minecraft/entity/boss/dragon/EnderDragonPart;Lnet/minecraft/entity/damage/DamageSource;F)Z"))
    public boolean damagePart(EnderDragonEntity instance, EnderDragonPart part, DamageSource source, float amount){
        if(instance.hurtTime > 0){return instance.damagePart(part, source, amount);}
        if (!MathDragon.CONFIG.useMathDragon || !MathDragon.CONFIG.switchFunction.dragon){return instance.damagePart(part, source, amount);}
        if (source.getAttacker() instanceof PlayerEntity){
            if (instance.getWorld().isClient) {
                MathScreen.open(MathDragonFun.getRandomMathematical(), instance.getId(), amount);
            }
            return instance.damagePart(part, source, amount);
        }
        if(source.isOf(DamageTypes.BAD_RESPAWN_POINT)){
            int SIZE = 10;
            List<PlayerEntity> playerEntities = instance.getWorld().getNonSpectatingEntities(PlayerEntity.class, instance.getBoundingBox().expand(SIZE));
            if (playerEntities.isEmpty()){
                return false;
            }
            if (!instance.getWorld().isClient) {
                int i = Random.create().nextBetween(0, playerEntities.size() - 1);
                PacketByteBuf buf = PacketByteBufs.create();
                buf.writeInt(instance.getId());
                buf.writeFloat(amount);
                ServerPlayNetworking.send((ServerPlayerEntity) playerEntities.get(i), NetWorkingPackId.ToPlayer, buf);
            }
            return false;

        }
        return instance.damagePart(part, source, amount);
    }
}
